# from typing import List
#
# from Crypto.Hash import MD5
#
# from common.io.file_service import FileService

import backoff
import base64
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from Crypto.Hash import MD5
from Crypto.Signature import PKCS1_v1_5
from requests.exceptions import RequestException
from httpx import Client
from typing import List
import httpx
from httpx import Client


class KnowledgeBaseClient:
    def __init__(self, url: str, kbs_url: str, private_key: str, http_client: Client):
        self.url = url
        self.kbs_url = kbs_url
        self.private_key = private_key
        self._client = http_client

    def get_header(self, knowledge_point_ids: List[str]) -> dict:
        plaintext = {"pointIdList": knowledge_point_ids, "sourceCode": "IOP_RAG"}
        return {
            'sourceCode': 'IOP_RAG',
            'sign': self.get_sign(plaintext),
            'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
            'Content-Type': 'application/json'
        }

    def get_header_common(self, body: dict) -> dict:
        body.update({"sourceCode": "IOP_RAG"})
        return {
            'sourceCode': 'IOP_RAG',
            'sign': self.get_sign(body),
            'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
            'Content-Type': 'application/json'
        }

    def get_sign(self, param_dict: dict) -> str:
        # 对传递的非空参数->按序(按参数名的顺序)组装成明文串->使用MD5生成摘要->使用RSA对MD5摘要进行签名
        keys = sorted(param_dict.keys())
        str_param = '&'.join(['{}={}'.format(key, param_dict[key]) for key in keys if param_dict[key]])
        # 将单引号替换成双引号
        str_param = str_param.replace("'", '"')
        # 把空格去掉
        str_param = str_param.replace(" ", "")
        md5 = MD5.new()
        md5.update(str_param.encode('utf-8'))
        md5_value = md5.hexdigest()
        signature = self.rsa_sign(md5_value)
        return signature

    def rsa_sign(self, md5_digest: str) -> str:
        # 使用RSA对MD5摘要进行签名
        cipher = PKCS1_v1_5.new(RSA.importKey(base64.standard_b64decode(self.private_key)), )  # 生成一个加密的类
        # return base64.standard_b64encode(cipher.encrypt(md5_digest.encode('utf-8')))  # 对数据进行加密    from Crypto.Cipher import PKCS1_v1_5
        return base64.standard_b64encode(
            cipher.sign(MD5.new(md5_digest.encode('utf-8'))))  # 对数据进行签名！  from Crypto.Signature import PKCS1_v1_5

    @backoff.on_exception(backoff.expo, exception=RequestException, max_tries=3)
    def get_knowledge_base_info_service(self, knowledge_point_ids: List[str]) -> dict:
        """ 获取知识库数据 """
        params = {
            "pointIdList": knowledge_point_ids
        }
        headers = self.get_header_common(params)
        try:
            response = self._client.post(self.url, headers=headers, json=params, timeout=60)
            if response.status_code != 200:
                raise Exception(f"1.获取知识库失败: response: {response.text}")
            if not response.is_success:
                raise Exception(f"2.获取知识库失败: response: {response.text}")
            if response.json().get('code', "999") == '0' and response.json().get('data', {}):
                return response.json().get('data')
            else:
                raise Exception(f"3.获取知识库失败: response: {response.text}")
        except Exception as e:
            raise Exception(f"获取知识库错误: detail: {e}")

    @backoff.on_exception(backoff.expo, exception=RequestException, max_tries=3)
    def get_knowledge_point_ids_service(self, main_knowledge_point_id: List[str]) -> dict:
        """ 获取知识库doc_ids """
        params = {
            "knowId": main_knowledge_point_id
        }
        headers = self.get_header_common(params)
        try:
            response = self._client.post(self.kbs_url, headers=headers, json=params, timeout=60)
            if response.status_code != 200:
                raise Exception(f"1.获取知识库doc_ids失败: response: {response.text}")
            if not response.is_success:
                raise Exception(f"2.获取知识库doc_ids失败: response: {response.text}")
            if response.json().get('code', "999") == '0' and response.json().get('data', {}):
                return response.json().get('data')
            else:
                raise Exception(f"3.获取知识库doc_ids失败: response: {response.text}")
        except Exception as e:
            raise Exception(f"获取知识库doc_ids错误: detail: {e}")

    def _send_request(self, url: str, param_dict: dict) -> dict:
        sign = self.get_sign(param_dict)
        headers = {
            'Content-Type': 'application/json',
            'sourceCode': 'IOP_RAG',
            'sign': sign
        }
        try:
            response = self._client.post(url, headers=headers, json=param_dict, timeout=60)
            if response.status_code != 200:
                raise Exception(f"1.知识库接口请求失败: url:{url} response: {response.text}")
            if not response.is_success:
                raise Exception(f"2.知识库接口请求失败: url:{url} response: {response.text}")
            return response.json()
        except Exception as e:
            raise Exception(f"知识库接口请求错误: detail: {e}")


def create_http_client(max_keepalive_connections=5,
                       max_connections=10,
                       retries=2,
                       timeout=3.0,
                       connect_timeout=3.0) -> Client:
    """
    同步的http客户端

    @param max_keepalive_connections:  最大保持连接数
    @param max_connections:  最大连接数
    @param retries:  重试次数
    @param timeout:  超时时间
    @param connect_timeout:  连接超时时间
    @return:  http客户端
    """
    timeout = httpx.Timeout(timeout=timeout, connect=connect_timeout)
    limits = httpx.Limits(max_keepalive_connections=max_keepalive_connections, max_connections=max_connections)
    transport = httpx.HTTPTransport(retries=retries)
    return httpx.Client(limits=limits, transport=transport, timeout=timeout)


http_client = create_http_client(max_connections=5,
                                      max_keepalive_connections=2,
                                      retries=2,
                                      timeout=10,
                                      connect_timeout=3)


def get_doc_prod(doc_ids):
    knowledge_base_client = KnowledgeBaseClient(url='https://aigc.midea.com/knowledge-mgr/api/doc/queryDocFile',
                                                     kbs_url='aa',
                                                     private_key='MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCbGpsWUK4eQ/9aF04QqNNe64hofYHS0OamJxTBNPaLBZq9s8p34ai643/uFOee6MdF6ARWvV8dbvga8sEcemn8oDw0P4PlA5Jmk2JlW9V2Hn1dMsYBAMOsxH8s5uUxLWAOKlijDH2kinxBDYZSZ6b4lmXAjQxKy8Qt/5ASb+nl09qulQWUYl72eJHKe3tiYbB4DA2zmR/fiRDjTtvSG4Lv/kKYsHt0gYZczB7D6Wnvym/cIKCRq0pXgrjAQ8lJHHoyvr2Q1fLA1Imrk4z4uJEcGhyQnpU5whuB22grv7sDYUAdfFXwRQenL8ckDzxfOQdIw4/fY6FR04DVFqLiGDtFAgMBAAECggEAYw1Jr6WUnLV2FJW/f/ohCoRGV9yXFQfd1Iwuv/hP3paUrMNt8MNG2xtAbs4g4SXtZOJ4KuDDJmvgvGz9EG/I0dGOwRsy4wU18JX9B5fvKYDtNKChPLC9Rc8zHHzUL2S37DP06SOn9XWPRogZmPSi+CwsDRzGldmtjmagHnYkHGYBtfPh7N4iPu+lkx8Uf2Lyj6R+haMOXROEcv2WrdfaSxRf2Tru4dmvNKmi4K9PdviIGCaBNnYibj0AX8gak2B4urJFVPrPBLHLU8iShJu6llDHG6mPWjoWuNPGTRb9txR0nh2vLYyJLRh43a0YVywOLARooR5iCtseN3P80iBnoQKBgQDLuNGGhcPPzo+PaI6mUBcKSZcLH+++E3A+sWWLKwdSDY6TctNuCFbz3aiIX45m49HrWZuYhRSS+VBSdc1VNrhNsscKLiYArLQzJfD5gCX16HY3F8bdawmhNOWgZBHXYn7Rao3r7SOhx/uAC9nQKGVHd2aMwuIAwLmqlKFgsk2i2QKBgQDC5+fkH71QISoIQYPffDkbX3BXkRnyWFPyjhbJyLkphT69PKlcJrVT+ezwI7z088kbamLFFyf7LlG5rKA3NuIHf87895vBLEanC0vwIxdOQplsDc2pghH6EM5SNOcFFHg/0UYuGSbyieXCMPBC/hGAN2wRP/PGa9fsaj7ng0hATQKBgHw5n/JywPuHzry5GjtKHTKVuzf6anuyaMCh9fSN8XHUeHtrCohPJ46fPHSkKDaPd2MXCi1QAUK6KoON9/6dVndyq7KGf3/r0BpcaXwK65ru/J8NraM48O9PTTKnssVu9zwFyLLzsMWnJ7JmB5TJ/TA+G9d7wsqIuu7MoTdQoszJAoGAe7h74booEPJMXRtBW57eHTsS8/L+lnBtMV3ypzoMF4gmUDduhjloBxtxxOnaq18IvKdmdReC4JYBeKxUs1faWMpPmRKQQyoY2zZ3iMKtq5bpDscgUsZnJOaAIXzFXNsmjdQJCYAb0f+o4gDwsoXWlB4aMkT3OHACi2bR8WHLfk0CgYAin8GurSRKS3k8T/tiN8MgxxmbSFe7bqYOxEAM0uUiR9AoSdgAsuLIcNlKNk6aJCLQlD83KfADeNZyj+78CrhEW8tmP2Y0M3q6Wi2ISgB3SeTf70r2m5kzzGLPAgQfWr9M+UTpOhl3Xpn+JVJn5Yn19BBtDKuUCLw283ti24h8IA==',
                                                     http_client=http_client)
    datas = knowledge_base_client.get_knowledge_base_info_service(list(doc_ids))
    print(datas)
    print('https://aigc.midea.com/robot/file/api/download?fileId=' + datas[0]['docFileId'])
    print('https://aigc.midea.com/robot/file/api/download?fileId=' + datas[0]['analyFileId'])


def get_doc_uat(doc_ids):
    # 测试
    knowledge_base_client = KnowledgeBaseClient(url='https://iopuat.midea.com/knowledge-mgr/api/doc/queryDocFile',
                                                     kbs_url='aa',
                                                     private_key='MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCY8B70mkqoZsTdCr5fB1i/k11paxqedyNxd1iRwIggf7aX6TMWjaY6yis7LV7JwPQQqYnz14Qse/Uhhd3roRVcwSPqUZhxX15zZR5hco2Kql0T4x0CjFeCVaCL2mu0u6bABLr2bH4bsoR5Nd8PzjGdr44ZzYIQB1MLzdZ+ml+Qy2Xq9qdIevTV9WDvNPlR25UkYyKwVptnlZFRUs4CeAR1m65EUjMRugjdC8Fx+ODxIQ548+y5Rb5asWavBAI2hzjbPi41mfRK2bfV2EB9fQhnAxJ6sF1b20pln7tMeOLLIm49p6CGWoUE4lPAa1WKackVJ0q0hD5xvEhpQAVPsTL5AgMBAAECggEBAJE6S5rovQZm+IASSK6CknLxJB4L164s4hpIQ3G8i0eZHzHn/1xmTDi9bAn4zm71bI46AEbuG5QGbcNUlGTBhUCcI1fJ/eGCt3UKy6urlN7dYh+VZiHaVOruFtNXKTnpi7IBi+yfH617erKDRnuCyLi9UUoNTXmdCu5Fm26Dd0ZNdXrGaiMGpsnK5PuStAL0/UOO6pEZfl5DmPAJbq9fwp8MLdN/RGgOSHvBTIgJeKTQx0O21KudEKAG4tgRBOZKkWaAJOKmp0ws3TjhUNZrlv9quiuZP8p9wHOFB7H9G84Ro9I4lz0cfpPgLc9Y92A0FQCViefcLc41v9u5oq1YCdUCgYEA24juiesVlzEjRZb7VGj4PEqbjokz1cUK4Y6iFbUT782PeTQW3KyBgyYGDq8Y+5FxL6U+XEjtE1Sf3x+NufMZz3NRPu98PXsWWHfMD4cIbuMX4BrbyMULz+Ai9R5abFN/5eJzVQAnoADNP1FKm+i+mBee6FwKgz86YFu31URA6F8CgYEAsldacbIEY5pCJR/xznMx0y2KGMQkdwJTkWZUskKgxKxD0ba2Og0yGlm7Ptwj4NKvLuET9PCZtf14EKMfEg/JrBc/dacfzuF72SNvannFdE/nWzy7ThZvmpG088ulHPrcM4bX7lpeqg8Gg9PWVh6PHHxOhlVoDGGUtZXpTrcvg6cCgYEAlGD1kMQSQLEWfOdyEXgtJ1rpzqnPHhHiq9bimDdeNTtDWJErTpVNp92gRHZ2NTn1PVW7U1Z63hDZSU4jVWYIsNzpMdddqpQx4zN8+ZWzznaw4Whl2knMFQERv4h3ZzX8gNzQRMgpAAzqrHv+KGhjwZpdbgEfnduzUgNLudo64JMCgYEArey3De6YjTKhk2cmATsiulrNNP4EufOQ4Fo1+2szMtr1gQ55hP/dfwlHrTQv4VBW/JcRSW1j2rKJZ2BOKuUuvyAlCW6lfLM2fzspq2N6h8ZtUPNXj/4ddVbobGKMckjMe4vkBlYnwB3LMsFjZLWEyDkKs8OTJ4/64WSEFfpc4j0CgYByj2UNn0JuNl6mJl/lvrkVnQ+GHM39m7MSDo+j781G/kqyb3vtJcNi5VY9YE0adLXkHEC3EFLQbOHl0UOnvF/ixuhkrKTJbZIDIrLZ79i3vU2pJgsZ8btYu8BDALbn5I28lV0Q02o1d8pEAYPAxC+HFye75gKwSHm+TbTteRoSaQ==',
                                                     http_client=http_client)
    datas = knowledge_base_client.get_knowledge_base_info_service(list(doc_ids))
    print(datas)
    print('https://iopuat.midea.com/robot/file/api/download?fileId='+datas[0]['docFileId'])
    print('https://iopuat.midea.com/robot/file/api/download?fileId='+datas[0]['analyFileId'])



if __name__ == '__main__':
        
    # file_service = FileService('https://aigc.midea.com/robot/file/api/download?fileId=',
    #                                 http_client)
    # data = file_service.get('iopcommon/fileSrv/202505/CS15DC20250523000157126365/CS30KI20241231000047555455.txt')
    # print(data)
    doc_ids = ['DC4be9f1a1258ccddf646957cf']
    # get_doc_uat(doc_ids)
    get_doc_prod(doc_ids)